#ifndef __MP_BOOST__
#define __MP_BOOST__

#include "../../include/bitmap.h"

namespace xm
{
	enum { PREFIX_LENGTH = 6 };
	enum { LOW_MASK = 0x20202020 };

	struct BloomFilter6 : public bit_map_t
	{
		enum { MIN_LENGTH = 6, };
		inline VOID add_binstr( LPCSTR binp, uint32_t iseed, uint32_t uOrMask )
		{
			setbit( hash_001(binp, iseed, LOW_MASK) );
			setbit( hash_002(binp, iseed, LOW_MASK) );
			setbit( hash_003(binp, iseed, LOW_MASK) );
			setbit( hash_004(binp, iseed, LOW_MASK) );
		}
		inline BOOL maybe_hit( LPCSTR binp, uint32_t iseed )
		{
			if( !testbit( hash_002(binp, iseed, LOW_MASK )) ) return FALSE;
			if( !testbit( hash_003(binp, iseed, LOW_MASK )) ) return FALSE;
			if( !testbit( hash_001(binp, iseed, LOW_MASK )) ) return FALSE;
			if( !testbit( hash_004(binp, iseed, LOW_MASK )) ) return FALSE;
			return TRUE;
		}
	protected:
		inline uint32_t hash_001( LPCSTR pb, uint32_t seed, uint32_t lowmask )
		{
			uint32_t tmp1 = (*((le::U32*)(pb+2)) | lowmask) + seed; seed <<= 5;
			uint32_t _hash = (*((le::U32*)(pb+1)) | lowmask) + seed; seed <<= 5;
			_hash ^= tmp1; _hash += seed;
			return _hash % bits();
		}
		inline uint32_t hash_002(LPCSTR pb, uint32_t seed, uint32_t lowmask )
		{
			uint32_t _hash = ((*(le::U32*)pb+1) | lowmask) ; _hash += seed;
			return _hash%bits();
		}
		inline uint32_t hash_003(LPCSTR pb, uint32_t seed, uint32_t lowmask )
		{
			le::U16 * p16 = (le::U16*)pb;
			uint32_t _hash = 0;
			_hash += (p16[0] | (uint16_t)lowmask); _hash <<= 3; _hash += seed; seed *= 0xF238907A;
			_hash += (p16[1] | (uint16_t)lowmask); _hash <<= 3; _hash += seed; seed *= 0xCD63A083;
			_hash += (p16[2] | (uint16_t)lowmask); _hash <<= 3; _hash += seed; seed *= 0x77315343;
			return _hash % bits();
		}
		inline uint32_t hash_004(LPCSTR pb, uint32_t seed, uint32_t lowmask )
		{
			uint32_t _hash = seed;
			_hash = (_hash * 3771 + ((uint8_t)lowmask|pb[0])) + seed; seed <<= 1;
			_hash = (_hash * 7317 + ((uint8_t)lowmask|pb[1])) + seed; seed <<= 2;
			_hash = (_hash * 3771 + ((uint8_t)lowmask|pb[2])) + seed; seed <<= 1;
			_hash = (_hash * 7317 + ((uint8_t)lowmask|pb[3])) + seed; seed <<= 2;
			_hash = (_hash * 3771 + ((uint8_t)lowmask|pb[4])) + seed; seed <<= 1;
			_hash = (_hash * 7317 + ((uint8_t)lowmask|pb[5])) + seed; seed <<= 2;
			return _hash % bits();
		}
	};

	struct ShiftTableS2
	{
		static inline uint16_t hashv( LPCSTR binp )
		{
			return (*(le::U16*)(binp-1)) | 0x2020; 
		}
		enum { SUFFIX_BYTES = sizeof(uint16_t), };
		enum { TABLE_SIZE	= 0x10000 };

		uint8_t			_shift[TABLE_SIZE];

		inline ShiftTableS2()
		{
			clear();
		}

		inline VOID clear()
		{
			memset( _shift, PREFIX_LENGTH-SUFFIX_BYTES, TABLE_SIZE );
		}
		inline BOOL add_binstr( LPCSTR binp )
		{
			if( !_shift ) FALSE;
			size_t sLast = PREFIX_LENGTH - 1;
			size_t sFirst = 1;
			for (size_t j = sLast; sFirst <= j; --j)
			{
				uint16_t hash = hashv(binp+j);
				size_t shift = sLast - j;
				if (shift < _shift[hash]) 
					_shift[hash] = (uint8_t)shift;
			}
			return TRUE;
		}
		inline size_t get_shift( uint16_t _hash )
		{
			return _shift[_hash];
		}
	};

};


#endif